﻿using System;
using System.Data.SqlClient;
using System.Globalization;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Controls;
using System.Windows.Media;
using Tools;
using WPF数据采集系统.BLL;

namespace WPF数据采集系统.ViewModel
{
    public class PlcTool
    {
        [DllImport("kernel32")]
        public static extern int GetPrivateProfileString(string section, string key, string defVal, StringBuilder retVal, int size, string filePath);
        [DllImport("kernel32")]
        public static extern long WritePrivateProfileString(string section, string key, string val, string filePath);

        public PlcTool()
        {

        }
        #region 配置文件读写
        public static string IniRead(string section, string key, string path)
        {
            StringBuilder temp = new StringBuilder(255);
            int i = GetPrivateProfileString(section, key, "", temp, 255, path);
            return temp.ToString();
        }
        public static string IniWrite(string section, string key, string vall, string path)
        {
            StringBuilder temp = new StringBuilder(255);
            WritePrivateProfileString(section, key, vall, path);
            return temp.ToString();
        }
        #endregion

        #region   UDP通讯部分
        private IPEndPoint LocalPoint;
        private EndPoint RemotePoint;
        private Socket mySocket;

        public string localIP;
        public int localPort;
        public string remotoIP;
        public int remotoPort;
        public bool connstatus = false;//状态
        public string nodeaddress;
        public int plcId;
        object obj = new object();
        public static bool _isBusy=false;

        ~PlcTool()//析构函数，释放资源
        {
            if (mySocket != null)
            {
                mySocket.Dispose();
                mySocket = null;
            }
        }
        private void connetUDP()
        {
            try
            {
                //得到本机IP，设置UDP端口号     
                //LocalPoint = new IPEndPoint(IPAddress.Parse(localIP), localPort);
                //定义网络类型，数据连接类型和网络协议UDP  
                mySocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                mySocket.SendTimeout = 2000;
                mySocket.ReceiveTimeout = 2000;
                //得到客户机IP
                RemotePoint = new IPEndPoint(IPAddress.Parse(remotoIP), remotoPort);
                mySocket.Connect(RemotePoint);
                //绑定网络地址  
                //mySocket.Bind(LocalPoint);
            }
            catch (Exception ex)
            {
                mySocket.Close();
                throw ex;
            }

        }
        private void connetTCP()
        {
            //得到本机IP，设置UDP端口号     
            LocalPoint = new IPEndPoint(IPAddress.Parse(localIP), localPort);
            //定义网络类型，数据连接类型和网络协议UDP  
            mySocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            mySocket.SendTimeout = 500;
            mySocket.ReceiveTimeout = 500;
            //绑定网络地址  
            //mySocket.Bind(LocalPoint);

            //建立连接           
        }
        public void UDP_Close()
        {
            mySocket.Close();
        }

        public bool write(string Memory_Type, int Start_address, int count, int[] data)
        {
            lock(obj)
            {
                //int indexof = remotoIP.LastIndexOf('.') + 1;
                //nodeaddress = remotoIP.Substring(12, remotoIP.Length - 12);
                //nodeaddress = remotoIP.Substring(indexof, remotoIP.Length - indexof);
                byte[] message = getfinscommand(Memory_Type, Start_address, count, true, data);
                if (mySocket == null) { connetUDP(); }
                byte[] revdata = new byte[1024];
                try
                {
                    mySocket.SendTo(message, message.Length, SocketFlags.None, RemotePoint);
                    mySocket.ReceiveFrom(revdata, ref RemotePoint);
                    connstatus = true;
                    return connstatus;
                }
                catch (Exception ex)
                {
                    connstatus = false;
                    throw ex;
                }
            }
        }
        public byte[] readTcp()
        {
            lock (obj)
            {
                int indexof = remotoIP.LastIndexOf('.') + 1;
                //nodeaddress = remotoIP.Substring(11, remotoIP.Length - 11);
                nodeaddress = remotoIP.Substring(indexof, remotoIP.Length - indexof);
                int[] temp = new int[0];
                byte[] message = getfinscommandTCP();//FINS命令解析

                if (mySocket == null)
                { connetTCP(); }//connetUDP
                byte[] revdata = new byte[1024];
                try
                {
                    //得到客户机IP  
                    RemotePoint = new IPEndPoint(IPAddress.Parse(remotoIP), remotoPort);
                    mySocket.Send(message, 0, message.Length, SocketFlags.None);//发送数据
                    mySocket.ReceiveFrom(revdata, ref RemotePoint);//接收数据
                    connstatus = true;
                    return revdata;
                }
                catch (Exception ex)
                {
                    connstatus = false; ;
                    throw ex;
                }
            }
        }
        /// <summary>
        /// 读取
        /// </summary>
        /// <param name="Memory_Type"></param>
        /// <param name="Start_address"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public void ReadInt(string Memory_Type, int Start_address, int count,out DataResult<byte[]> dr_read)
        {
            dr_read = new DataResult<byte[]>();//返回结果
            try
            {
                lock (obj)
                {
                    //int indexof = remotoIP.LastIndexOf('.') + 1;
                    //nodeaddress = remotoIP.Substring(11, remotoIP.Length - 11);
                    //nodeaddress = remotoIP.Substring(indexof, remotoIP.Length - indexof);
                    int[] temp = new int[0];
                    byte[] message = getfinscommand(Memory_Type, Start_address, count, false, temp);//FINS命令解析
                    if (mySocket == null) { connetUDP(); }//connetUDP
                    byte[] revdata = new byte[count * 2+ 14];
                    connstatus = true;
                    mySocket.SendTo(message, message.Length, SocketFlags.None, RemotePoint);//发送数据
                    mySocket.ReceiveFrom(revdata, ref RemotePoint);//接收数据
                    dr_read.State = true;
                    dr_read.code = 1;
                    dr_read.Data = revdata;// GetFinsDataInt(revdata, count);
                    connstatus = false;
                }
            }
            catch (Exception ex)
            {
                connstatus = false;
                dr_read.code = ex.HResult;
                dr_read.State = false;
                dr_read.Message = "错误消息:"+ex.Message + " 导致异常的实例:" +ex.InnerException+ " 对象名:"+ ex.Source+" 函数名:" +ex.TargetSite;
            }
        }
        public float[] ReadReal(string Memory_Type, int Start_address, int count)
        {
            lock (obj)
            {
                int indexof = remotoIP.LastIndexOf('.') + 1;
                //nodeaddress = remotoIP.Substring(11, remotoIP.Length - 11);
                nodeaddress = remotoIP.Substring(indexof, remotoIP.Length - indexof);
                int[] temp = new int[0];
                byte[] message = GetFinsCommandFour(Memory_Type, Start_address, count, false, temp);//FINS命令解析

                if (mySocket == null) { connetUDP(); }
                byte[] revdata = new byte[1024];
                try
                {
                    mySocket.SendTo(message, message.Length, SocketFlags.None, RemotePoint);//发送数据
                    mySocket.ReceiveFrom(revdata, ref RemotePoint);//接收数据
                    connstatus = true;
                    return GetFinsDataReal(revdata, count);
                }
                catch (Exception ex)
                {
                    connstatus = false;
                    throw ex;
                }
            }
        }
        #endregion
        #region   FINS命令解析
        /// <summary>
        /// 获取fins命令帧
        /// </summary>
        /// <param name="Memory_Type">内存类型 D,CIO,WR,HR,AR</param>
        /// <param name="Start_address">开始地址</param>
        /// <param name="count">数据长度 0-255</param>
        /// <param name="iswritemesssage">读或写？</param>
        /// <param name="writemesssage">int[]类型</param>
        /// <returns>sendBytes返回数据</returns>
        private byte[] getfinscommand(string Memory_Type, int Start_address, int count, bool iswritemesssage, int[] writemesssage)
        {

            int data1 = 0;
            int data2 = 0;
            int data3 = 0;
            int memory_type = 0;
            if (Start_address <= 255)
            {
                data1 = 0;
                data2 = Start_address;
                data3 = 0;
            }
            else
            {
                int a = Start_address;
                data1 = a / 256;
                data2 = a % 256;
                data3 = 0;
            }
            switch (Memory_Type)
            {
                case "DM":
                    memory_type = 0x82;
                    break;
                case "CIO":
                    memory_type = 0xb0;
                    break;
                case "WR":
                    memory_type = 0xb1;
                    break;
                case "HR":
                    memory_type = 0xb2;
                    break;
                case "AR":
                    memory_type = 0xb3;
                    break;
            }
            byte[] sendByes = new byte[18 + (writemesssage.Length * 2)];
            sendByes[0] = 0x80;
            sendByes[1] = 0x0;
            sendByes[2] = 0x2;
            sendByes[3] = 0x0;
            sendByes[4] = 0x1;
            sendByes[5] = 0x0;
            sendByes[6] = 0x0;
            sendByes[7] = 0x2;
            sendByes[8] = 0x0;
            sendByes[9] = 0x2;
            sendByes[10] = 0x1;
            if (iswritemesssage)
            { sendByes[11] = 0x2; }
            else
            {
                sendByes[11] = 0x1;
            }
            sendByes[12] = Convert.ToByte(memory_type);
            sendByes[13] = Convert.ToByte(data1);
            sendByes[14] = Convert.ToByte(data2);
            sendByes[15] = Convert.ToByte(data3);
            sendByes[16] = 0x0;
            sendByes[17] = Convert.ToByte((count).ToString());
            if (iswritemesssage == true & writemesssage.Length > 0)
            {
                int j = 0;
                for (int i = 18; i < (18 + writemesssage.Length * 2); i = i + 2)
                {
                    if (writemesssage[j] <= 255)
                    {
                        sendByes[i] = 0;
                        sendByes[i + 1] = Convert.ToByte(writemesssage[j]);
                    }
                    else
                    {
                        int a = writemesssage[j];
                        sendByes[i] = Convert.ToByte(a / 256);
                        sendByes[i + 1] = Convert.ToByte(a % 256);
                    }
                    j++;
                }
            }
            return sendByes;
        }
        private byte[] GetFinsCommandFour(string Memory_Type, int Start_address, int count, bool iswritemesssage, int[] writemesssage)
        {

            int data1 = 0;
            int data2 = 0;
            int data3 = 0;
            int memory_type = 0;
            if (Start_address <= 255)
            {
                data1 = 0;
                data2 = Start_address;
                data3 = 0;
            }
            else
            {
                int a = Start_address;
                data1 = a / 256;
                data2 = a % 256;
                data3 = 0;
            }
            switch (Memory_Type)
            {
                case "DM":
                    memory_type = 0x82;
                    break;
                case "CIO":
                    memory_type = 0xb0;
                    break;
                case "WR":
                    memory_type = 0xb1;
                    break;
                case "HR":
                    memory_type = 0xb2;
                    break;
                case "AR":
                    memory_type = 0xb3;
                    break;
            }
            byte[] sendByes = new byte[18 + (writemesssage.Length * 2)];
            sendByes[0] = 0x80;
            sendByes[1] = 0x0;
            sendByes[2] = 0x2;
            sendByes[3] = 0x0;
            sendByes[4] = 0x1;
            sendByes[5] = 0x0;
            sendByes[6] = 0x0;
            sendByes[7] = 0x2;
            sendByes[8] = 0x0;
            sendByes[9] = 0x2;
            sendByes[10] = 0x1;
            if (iswritemesssage)
            { sendByes[11] = 0x2; }
            else
            {
                sendByes[11] = 0x1;
            }
            sendByes[12] = Convert.ToByte(memory_type);
            sendByes[13] = Convert.ToByte(data1);
            sendByes[14] = Convert.ToByte(data2);
            sendByes[15] = Convert.ToByte(data3);
            sendByes[16] = 0x0;
            sendByes[17] = Convert.ToByte((count * 2).ToString());
            if (iswritemesssage == true & writemesssage.Length > 0)
            {
                int j = 0;
                for (int i = 18; i < (18 + writemesssage.Length * 2); i = i + 2)
                {
                    if (writemesssage[j] <= 255)
                    {
                        sendByes[i] = 0;
                        sendByes[i + 1] = Convert.ToByte(writemesssage[j]);
                    }
                    else
                    {
                        int a = writemesssage[j];
                        sendByes[i] = Convert.ToByte(a / 256);
                        sendByes[i + 1] = Convert.ToByte(a % 256);
                    }
                    j++;
                }
            }
            return sendByes;
        }
        private byte[] getfinscommandTCP()
        {
            byte[] sendByes = new byte[20];
            sendByes[0] = 0x46;
            sendByes[1] = 0x49;
            sendByes[2] = 0x4e;
            sendByes[3] = 0x53;
            sendByes[4] = 0x0;
            sendByes[5] = 0x0;
            sendByes[6] = 0x0;
            sendByes[7] = 0x0c;
            sendByes[8] = 0x0;
            sendByes[9] = 0x0;
            sendByes[10] = 0x0;
            sendByes[11] = 0x0;
            sendByes[12] = 0x0;
            sendByes[13] = 0x0;
            sendByes[14] = 0x0;
            sendByes[15] = 0x0;
            sendByes[16] = 0x0;
            sendByes[17] = 0x0;
            sendByes[18] = 0x0;
            sendByes[19] = 0x0;
            return sendByes;
        }
        public static int[] GetFinsDataInt(byte[] receiveBytes, int count)
        {
            int[] data = new int[count];
            int index = 0;
            for (int i = 14; i < 14 + count * 2; i = i + 2)
            {
                int a = receiveBytes[i];
                int b = receiveBytes[i + 1];
                if (receiveBytes[i] == 0)
                {
                    data[index] = b;
                }
                else
                {
                    int d = (receiveBytes[i] * 256) + receiveBytes[i + 1];
                    data[index] = d;
                }
                index++;
            }
            return data;
        }
        public static float[] GetFinsDataReal(byte[] receiveBytes, int count)
        {
            int index = 0;
            float[] data = new float[count];
            for (int i = 14; i < 14 + count * 4; i = i + 4)
            {
                byte[] b = new byte[4];
                b[0] = receiveBytes[i + 1];
                b[1] = receiveBytes[i];
                b[2] = receiveBytes[i + 3];
                b[3] = receiveBytes[i + 2];
                data[index] = (float)Math.Round((double)BitConverter.ToSingle(b, 0), 2);
                index++;
            }
            return data;
        }

        #endregion
        #region 数组比较是否相等
        /// <summary>
        /// 数组比较是否相等
        /// </summary>
        /// <param name="bt1">数组1</param>
        /// <param name="bt2">数组2</param>
        /// <returns>true:相等，false:不相等</returns>
        public static bool CompareArray(int[] bt1, int[] bt2)
        {
            int len1 = bt1.Length;
            int len2 = bt2.Length;
            if (len1 != len2)
            {
                return false;
            }
            for (int i = 0; i < len1; i++)
            {
                if (bt1[i] != bt2[i])
                    return false;
            }
            return true;
        }
        /// <summary>
        /// 401项目专用
        /// </summary>
        /// <param name="data"></param>
        /// <param name="danhao"></param>
        /// <param name="username"></param>
        /// <returns></returns>
        public static string[] ByteArrayToHexString(byte[] data, string danhao, string username)
        {//字节数组转化为16进制字符串
         //StringBuilder sb = new StringBuilder(data.Length * 3);
            try
            {
                string[] retu = new string[data.Length];
                for (int i = 0; i < data.Length; i++)
                {
                    string value = Convert.ToString(data[i], 16).PadLeft(2, '0').ToUpper();
                    retu[i] = value;
                }
                if (data.Length == 25 && !string.IsNullOrWhiteSpace(danhao))
                {
                    string dtNow = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                    string[] sb = new string[13];
                    sb[0] = int.Parse((Convert.ToString(data[6], 16) + Convert.ToString(data[7], 16)), NumberStyles.AllowHexSpecifier).ToString();
                    sb[1] = int.Parse((Convert.ToString(data[8], 16) + Convert.ToString(data[9], 16)), NumberStyles.AllowHexSpecifier).ToString();
                    sb[2] = int.Parse((Convert.ToString(data[10], 16) + Convert.ToString(data[11], 16)), NumberStyles.AllowHexSpecifier).ToString();
                    sb[3] = int.Parse((Convert.ToString(data[12], 16) + Convert.ToString(data[13], 16)), NumberStyles.AllowHexSpecifier).ToString();

                    sb[4] = Convert.ToString(data[14], 16);
                    if (Convert.ToString(data[14], 16).ToLower() == "ff")
                    {
                        sb[4] = "OC";
                    }
                    else if (Convert.ToString(data[14], 16).ToLower() == "1")
                    {
                        sb[4] = "非OC";
                    }
                    else
                    {
                        sb[4] = "无结果";
                    }
                    sb[5] = Convert.ToString(data[15], 16);
                    if (Convert.ToString(data[15], 16).ToLower() == "ff")
                    {
                        sb[5] = "NG";
                    }
                    else { sb[5] = "OK"; }

                    sb[6] = Convert.ToString(data[16], 16);
                    if (Convert.ToString(data[16], 16).ToLower() == "ff")
                    {
                        sb[6] = "NG";
                    }
                    else { sb[6] = "OK"; }

                    sb[7] = Convert.ToString(data[17], 16);
                    if (Convert.ToString(data[17], 16).ToLower() == "ff")
                    {
                        sb[7] = "NG";
                    }
                    else { sb[7] = "OK"; }

                    sb[8] = Convert.ToString(data[18], 16);
                    if (Convert.ToString(data[18], 16).ToLower() == "ff")
                    {
                        sb[8] = "NG";
                    }
                    else { sb[8] = "OK"; }
                    sb[9] = Convert.ToString(data[19], 16);
                    if (Convert.ToString(data[19], 16).ToLower() == "ff")
                    {
                        sb[9] = "NG";
                    }
                    else { sb[9] = "OK"; }

                    sb[10] = Convert.ToString(data[20], 16);
                    if (Convert.ToString(data[20], 16).ToLower() == "ff")
                    {
                        sb[10] = "NG";
                    }
                    else { sb[10] = "OK"; }

                    sb[11] = Convert.ToString(data[21], 16);
                    if (Convert.ToString(data[21], 16).ToLower() == "ff")
                    {
                        sb[11] = "NG";
                    }
                    else { sb[11] = "OK"; }

                    sb[12] = Convert.ToString(data[22], 16);
                    if (Convert.ToString(data[22], 16).ToLower() == "ff")
                    {
                        sb[12] = "NG";
                    }
                    else
                    {
                        sb[12] = "OK";
                    }
                    string sql = "INSERT INTO [dbo].[TestResult](日期,跌落1,跌落2,VP电压,升压时间,开路结果,放电1,放电2,VP结果,跌落1结果" +
               ",跌落2结果,TL结果,TH结果,总结果 ,单号,操作人) VALUES(@date,@sb0,@sb1,@sb2,@sb3,@sb4,@sb5,@sb6,@sb7,@sb8,@sb9,@sb10,@sb11,@sb12,@danhao,@caozuoren)";
                    SqlParameter[] param1 = new SqlParameter[]
                    {
                    new SqlParameter("@date",dtNow),
                    new SqlParameter("@sb0",sb[0]),
                    new SqlParameter("@sb1",sb[1]),
                    new SqlParameter("@sb2",sb[2]),
                    new SqlParameter("@sb3",sb[3]),
                    new SqlParameter("@sb4",sb[4]),
                    new SqlParameter("@sb5",sb[5]),
                    new SqlParameter("@sb6",sb[6]),
                    new SqlParameter("@sb7",sb[7]),
                    new SqlParameter("@sb8",sb[8]),
                    new SqlParameter("@sb9",sb[9]),
                    new SqlParameter("@sb10",sb[10]),
                    new SqlParameter("@sb11",sb[11]),
                    new SqlParameter("@sb12",sb[12]),
                    new SqlParameter("@danhao",danhao),
                     new SqlParameter("@caozuoren",username)
                    };
                    SqlHelper.Update(sql, param1);
                    return sb;
                }
                else if (data.Length == 9 && data[4] != 15)
                {
                    string dtNow = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                    string reson = String.Empty;
                    int error = int.Parse((Convert.ToString(data[6], 16) + Convert.ToString(data[7], 16)), NumberStyles.AllowHexSpecifier);
                    switch (error)
                    {
                        case 1:
                            reson = "校验和错误";
                            break;
                        case 2:
                            reson = "命令类型错误";
                            break;
                        case 3:
                            reson = "命令字错误";
                            break;
                        case 4:
                            reson = "状态不符";
                            break;
                        case 5:
                            reson = "参数错误:参数无效或个数不符";
                            break;
                        default:
                            reson = "正常";
                            break;
                    }
                    string errorDH = danhao;
                    string sql = "INSERT INTO  [dbo].[error_log](日期,错误代码,错误原因,单号) VALUES(@s1,@s2,@s3,@s4)";
                    SqlParameter[] param1 = new SqlParameter[]
                    {
                    new SqlParameter("@s1",dtNow),
                    new SqlParameter("@s2",error),
                    new SqlParameter("@s3",reson),
                    new SqlParameter("@s4",errorDH)
                    };
                    SqlHelper.Update(sql, param1);
                }
                return retu;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public static byte[] HexStringToByteArray(string s)
        {//16进制字符串转化为字节数组
            s = s.Replace(" ", "");
            byte[] buffer = new byte[s.Length / 2];
            for (int i = 0; i < s.Length; i += 2)
                buffer[i / 2] = (byte)Convert.ToByte(s.Substring(i, 2), 16);
            return buffer;
        }
        /// <summary>
        /// 将字符串转为16进制字符，允许中文
        /// </summary>
        /// <param name="s"></param>
        /// <param name="encode"></param>
        /// <returns></returns>
        public static string StringToHexString(string s, Encoding encode, string spanString)
        {
            byte[] b = encode.GetBytes(s);//按照指定编码将string编程字节数组
            string result = string.Empty;
            for (int i = 0; i < b.Length; i++)//逐字节变为16进制字符
            {
                result += Convert.ToString(b[i], 16) + spanString;
            }
            return result;
        }
        #endregion
    }
}
